import os
import sys

import PySide6
from PySide6 import QtCore
from PySide6.QtCore import Qt, Signal, QRect, QPoint
from PySide6.QtGui import QIcon, QMouseEvent
from PySide6.QtWidgets import QWidget, QApplication, QGridLayout, QLabel, QProgressBar, QGroupBox, QPushButton, \
    QSizePolicy, QCheckBox, QLineEdit, QComboBox, QStackedWidget, QFileDialog, QMessageBox
import resources.resources_rc

class Struct_Write_Manage(QWidget):
    def __init__(self, parent=None, config=None, sizelist=[], com_online_action=QPushButton):
        super().__init__()
        # 获取变量
        self.config = config
        self.signal_operat = parent.signal_operat
        self.queue_logging = parent.queue_logging
        self.size_list = sizelist
        self.com_online_action = com_online_action
        # 创建变量
        self.length_pack = 2000
        self.send_batch_data_index = 0
        self.send_index_index = 0
        self.tuple_dict_key = []
        self.tuple_list = []
        self.tuple_dict = {}
        # 创建定时器
        self.send_batch_data_timer = QtCore.QTimer()  # 发送大量数据时所用的定时器
        self.send_batch_data_timer.timeout.connect(self.send_batch_data_slot)
        self.send_batch_data_timer.setSingleShot(False)
        self.send_batch_data_timer2 = QtCore.QTimer()  # 发送大量数据时所用的定时器
        self.send_batch_data_timer2.timeout.connect(self.send_batch_data_slot2)
        self.send_batch_data_timer2.setSingleShot(False)
        self.recover_scope_timer = QtCore.QTimer()  # 用于恢复scope状态的的定时器
        self.recover_scope_timer.timeout.connect(self.recover_scope_slot)
        self.recover_scope_timer.setSingleShot(True)

        self.initLayout()
        self.read_config()
        self.show()

    def initLayout(self):
        """ 创建视图 """
        # 初始化窗口
        self.setWindowTitle('下载数据')
        # self.setFixedSize(500, 400)
        self.setMinimumHeight(400)
        self.setMinimumWidth(500)
        self.setWindowIcon(QIcon(':/logo.ico'))
        self.layout = QGridLayout(self)

        # 进度条
        self.label_progress = QLabel('下载进度:')
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 2000)
        self.progress_bar.setValue(0)

        # 显示进度
        self.label_text = QLabel()
        self.label_text.setFixedHeight(15)

        # 布置窗口
        self.stack_widget = QStackedWidget()
        self.group_file = ClickableGroupBox('合并配置')
        self.group_file.clicked.connect(self.stack_view_change_slot)
        self.layout_file = QGridLayout(self.group_file)
        self.group_file2 = ClickableGroupBox('单项配置')
        self.group_file2.clicked.connect(self.stack_view_change_slot)
        self.layout_file2 = QGridLayout(self.group_file2)
        self.stack_widget.addWidget(self.group_file)
        self.stack_widget.addWidget(self.group_file2)

        # 文件
        if self.size_list:
            self.create_file_layout1(self.size_list, True)
            self.create_file_layout2(self.size_list, True)
        else:
            self.create_file_layout1([0], False)
            self.create_file_layout2([0], False)

        # 设置单个页面为主页
        self.stack_widget.setCurrentIndex(1)

        # self.create_file_layout1(4, True)
        # self.create_file_layout2(4, True)

        # 开始按钮
        self.button_action = QPushButton('开始')
        self.button_action.clicked.connect(self.button_action_slot)
        self.button_action.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        if self.size_list:
            self.button_action.setEnabled(True)
        else:
            self.button_action.setEnabled(False)

        # 添加layout
        self.layout.addWidget(self.label_progress, 0, 0, 1, 1)
        self.layout.addWidget(self.progress_bar, 0, 1, 1, 9)
        self.layout.addWidget(self.label_text, 1, 1, 1, 9)
        self.layout.addWidget(self.stack_widget, 2, 0, 4, 10)
        self.layout.addWidget(self.button_action, 6, 0, 2, 10)

    def stack_view_change_slot(self):
        if self.button_action.text() == '开始':
            if self.stack_widget.currentIndex() == 0:
                self.stack_widget.setCurrentIndex(1)
            else:
                self.stack_widget.setCurrentIndex(0)
        else:
            pass

    def create_file_layout1(self, size_list, enable):
        # self.label_select1 = QLabel('选择')
        # self.label_select1.setFixedSize(30, 30)
        # self.label_target_size1 = QLabel('目标尺寸')
        # self.label_name1 = QLabel('文件名称')
        # self.label_file_size1 = QLabel('文件尺寸')
        # self.label_read_button1 = QLabel('读取按钮')

        self.check_select_list = []
        self.label_size_list = []
        self.label_unit_list = []
        self.edit_filename_list = []
        self.label_file_size_list = []
        self.button_read_list = []
        for i in range(len(size_list)):
            check_select = QCheckBox()
            label_size = QLabel('0')
            label_unit = QLabel('byte')
            edit_filename = QLineEdit()
            edit_filename.setFocusPolicy(QtCore.Qt.NoFocus)
            edit_filename.setReadOnly(True)
            edit_filename.setFixedWidth(200)
            edit_filename.hex_data = None
            edit_filename.data_size = 0
            # label_file_size = QLabel('0')
            button_read = QPushButton('读取')
            button_read.clicked.connect(self.button_read_slot1)
            if enable and size_list[i] != 0:
                check_select.setEnabled(True)
                button_read.setEnabled(True)
                label_size.setText(str(self.size_list[i]))
            else:
                check_select.setEnabled(False)
                button_read.setEnabled(False)
            self.check_select_list.append(check_select)
            self.label_size_list.append(label_size)
            self.label_unit_list.append(label_unit)
            self.edit_filename_list.append(edit_filename)
            # self.label_file_size_list.append(label_file_size)
            self.button_read_list.append(button_read)

        # self.layout_file.addWidget(self.label_select1, 0, 0, 1, 3, Qt.AlignHCenter)
        # self.layout_file.addWidget(self.label_target_size1, 0, 3, 1, 3, Qt.AlignHCenter)
        # self.layout_file.addWidget(self.label_name1, 0, 6, 1, 8, Qt.AlignHCenter)
        # self.layout_file.addWidget(self.label_file_size1, 0, 14, 1, 3, Qt.AlignHCenter)
        # self.layout_file.addWidget(self.label_read_button1, 0, 17, 1, 3, Qt.AlignHCenter)
        # for i in range(len(size_list)):
        #     self.layout_file.addWidget(self.check_select_list[i], i+1, 0, 1, 3, Qt.AlignHCenter)
        #     self.layout_file.addWidget(self.label_size_list[i], i+1, 3, 1, 3, Qt.AlignHCenter)
        #     self.layout_file.addWidget(self.edit_filename_list[i], i+1, 6, 1, 8, Qt.AlignHCenter)
        #     self.layout_file.addWidget(self.label_file_size_list[i], i+1, 14, 1, 3, Qt.AlignHCenter)
        #     self.layout_file.addWidget(self.button_read_list[i], i+1, 17, 1, 3, Qt.AlignHCenter)

        for i in range(len(size_list)):
            self.layout_file.addWidget(self.check_select_list[i], i, 0, 1, 3, Qt.AlignHCenter)
            self.layout_file.addWidget(self.edit_filename_list[i], i, 3, 1, 8, Qt.AlignHCenter)
            self.layout_file.addWidget(self.label_size_list[i], i, 11, 1, 3, Qt.AlignRight)
            self.layout_file.addWidget(self.label_unit_list[i], i, 14, 1, 3, Qt.AlignLeft)
            self.layout_file.addWidget(self.button_read_list[i], i, 17, 1, 3, Qt.AlignHCenter)

    def create_file_layout2(self, size_list, enable):
        # self.label_select2 = QLabel('选择')
        # self.label_select2.setFixedSize(30, 30)
        # self.label_target_size2 = QLabel('目标尺寸')
        # self.label_name2 = QLabel('文件名称')
        # self.label_file_size2 = QLabel('文件尺寸')
        # self.label_read_button2 = QLabel('读取按钮')
        self.combox_index2 = QComboBox()
        self.combox_index2.setFixedWidth(60)
        for i in range(len(size_list)):
            if size_list[i] != 0:
                self.combox_index2.addItems(str(i))
        self.combox_index2.setCurrentIndex(0)
        # self.combox_index2.addItems([str(i) for i in range(count)])
        # self.label_size22 = QLabel('0')
        self.edit_filename2 = QLineEdit()
        self.edit_filename2.setFocusPolicy(QtCore.Qt.NoFocus)
        self.edit_filename2.setReadOnly(True)
        self.edit_filename2.setFixedWidth(200)
        self.edit_filename2.hex_data = None
        self.edit_filename2.data_size = 0
        self.label_size2 = QLabel('0')
        self.label_unit = QLabel('byte')
        self.button_read2 = QPushButton('读取')
        self.combox_index2.currentIndexChanged.connect(self.combox_change_slot)
        self.button_read2.clicked.connect(self.button_read_slot2)
        if enable:
            self.combox_index2.setEnabled(True)
            self.combox_change_slot()
            self.button_read2.setEnabled(True)
        else:
            self.combox_index2.setEnabled(False)
            self.button_read2.setEnabled(False)

        # self.layout_file2.addWidget(self.label_select2, 0, 0, 1, 3, Qt.AlignHCenter)
        # self.layout_file2.addWidget(self.label_target_size2, 0, 3, 1, 3, Qt.AlignHCenter)
        # self.layout_file2.addWidget(self.label_name2, 0, 6, 1, 8, Qt.AlignHCenter)
        # self.layout_file2.addWidget(self.label_file_size2, 0, 14, 1, 3, Qt.AlignHCenter)
        # self.layout_file2.addWidget(self.label_read_button2, 0, 17, 1, 3, Qt.AlignHCenter)
        # self.layout_file2.addWidget(self.combox_index2, 1, 0, 1, 3, Qt.AlignHCenter)
        # self.layout_file2.addWidget(self.label_size22, 1, 3, 1, 3, Qt.AlignHCenter)
        # self.layout_file2.addWidget(self.edit_filename2, 1, 6, 1, 8, Qt.AlignHCenter)
        # self.layout_file2.addWidget(self.label_size2, 1, 14, 1, 3, Qt.AlignHCenter)
        # self.layout_file2.addWidget(self.button_read2, 1, 17, 1, 3, Qt.AlignHCenter)
        self.layout_file2.addWidget(self.combox_index2, 0, 0, 1, 3, Qt.AlignHCenter)
        self.layout_file2.addWidget(self.edit_filename2, 0, 3, 1, 8, Qt.AlignHCenter)
        self.layout_file2.addWidget(self.label_size2, 0, 11, 1, 3, Qt.AlignRight)
        self.layout_file2.addWidget(self.label_unit, 0, 14, 1, 3, Qt.AlignLeft)
        self.layout_file2.addWidget(self.button_read2, 0, 17, 1, 3, Qt.AlignHCenter)

    def read_config(self):
        if self.config:
            for i in range(min(len(self.config['page0']['file_name']), len(self.edit_filename_list))):
                if i < len(self.size_list):
                    if self.size_list[i] != 0:
                        self.check_select_list[i].setChecked(self.config['page0']['check'][i])

                if os.path.exists(self.config['page0']['file_name'][i]):
                    self.edit_filename_list[i].setText(self.config['page0']['file_name'][i])
                    with open(self.config['page0']['file_name'][i], 'rb') as f:
                        data = f.read()
                        hex_data = data.hex()
                    # self.label_file_size_list[i].setText(str(int(len(hex_data) / 4)))
                    self.edit_filename_list[i].data_size = int(len(hex_data) / 2)
                    self.edit_filename_list[i].hex_data = [int(hex_data[i:i + 4], 16) for i in range(0, len(hex_data), 4)]
                else:
                    self.check_select_list[i].setChecked(False)
            # self.combox_index2.setCurrentIndex(self.config['page1']['combox'])
            self.combox_index2.setCurrentIndex(0)
            for i in range(self.combox_index2.count()):
                if self.config['page1']['combox'] == self.combox_index2.itemText(i):
                    self.combox_index2.setCurrentText(self.config['page1']['combox'])
            if os.path.exists(self.config['page1']['file_name']):
                self.edit_filename2.setText(self.config['page1']['file_name'])
                with open(self.config['page1']['file_name'], 'rb') as f:
                    data = f.read()
                    hex_data = data.hex()
                # self.label_size2.setText(str(int(len(hex_data) / 4)))
                self.edit_filename2.hex_data = [int(hex_data[i:i + 4], 16) for i in range(0, len(hex_data), 4)]
                self.edit_filename2.data_size = int(len(hex_data) / 2)
            self.stack_widget.setCurrentIndex(self.config['stack_index'])

    def get_config(self):
        config = {}
        config['page0'] = {}
        config['page0']['check'] = []
        config['page0']['file_name'] = []
        for i in range(len(self.check_select_list)):
            config['page0']['check'].append(self.check_select_list[i].isChecked())
            config['page0']['file_name'].append(self.edit_filename_list[i].text())
        config['page1'] = {}
        config['page1']['combox'] = self.combox_index2.currentText()
        config['page1']['file_name'] = self.edit_filename2.text()
        config['stack_index'] = self.stack_widget.currentIndex()
        self.config = config

    def button_read_slot1(self):
        index = self.button_read_list.index(self.sender())
        loadway = self.edit_filename_list[index].text()
        if loadway != '':
            if os.path.exists(loadway):
                pass
            else:
                loadway = '.'
        else:
            loadway = '.'
        # print(index)
        file_name, file_type = QFileDialog.getOpenFileName(self, '打开文件', loadway, '二进制文件文件(*.dat);;')
        # print(file_name)
        if file_name:
            self.edit_filename_list[index].setText(file_name)
            with open(file_name, 'rb') as f:
                data = f.read()
                hex_data = data.hex()
            # print(len(hex_data))
            self.edit_filename_list[index].hex_data = [int(hex_data[i:i + 4], 16) for i in range(0, len(hex_data), 4)]
            # self.label_file_size_list[index].setText(str(int(len(hex_data)/4)))
            self.edit_filename_list[index].data_size = int(len(hex_data)/2)
            self.check_select_list[index].setChecked(True)
            self.get_config()
        else:
            pass

    def button_read_slot2(self):
        loadway = self.edit_filename2.text()
        if loadway != '':
            if os.path.exists(loadway):
                pass
            else:
                loadway = '.'
        else:
            loadway = '.'
        file_name, file_type = QFileDialog.getOpenFileName(self, '打开文件', loadway, '二进制文件文件(*.dat);;')
        # print(file_name)
        if file_name:
            self.edit_filename2.setText(file_name)
            with open(file_name, 'rb') as f:
                data = f.read()
                hex_data = data.hex()
            # print(len(hex_data))
            self.edit_filename2.hex_data = [int(hex_data[i:i + 4], 16) for i in range(0, len(hex_data), 4)]
            # self.label_size2.setText(str(int(len(hex_data)/4)))
            self.edit_filename2.data_size = int(len(hex_data)/2)
            self.get_config()
        else:
            pass

    def combox_change_slot(self):
        if self.combox_index2.currentText() != '':
            self.label_size2.setText(str(self.size_list[int(self.combox_index2.currentText())]))

    def button_action_slot(self):
        if self.stack_widget.currentIndex() == 1:
            if self.button_action.text() == '开始':
                if self.label_size2.text() == '0':
                    QMessageBox.information(self, '提示', '目标尺寸不可为0!',QMessageBox.Yes)
                elif self.edit_filename2.hex_data is None:
                    QMessageBox.information(self, '提示', '请重新选取文件后重试!', QMessageBox.Yes)
                elif int(self.label_size2.text()) != self.edit_filename2.data_size:
                    QMessageBox.information(self, '提示', '文件尺寸与目标尺寸不一致!', QMessageBox.Yes)
                else:
                    self.tuple_list = list(((i,) + (len(tuple(self.edit_filename2.hex_data[i:i + self.length_pack])),) + tuple(self.edit_filename2.hex_data[i:i + self.length_pack])) for i in range(0, len(self.edit_filename2.hex_data), self.length_pack))
                    self.send_batch_data_index = 0
                    self.progress_bar.setRange(0, len(self.edit_filename2.hex_data))
                    self.progress_bar.setValue(0)
                    self.button_action.setEnabled(False)
                    self.button_action.setText('传输中')
                    self.set_widget_enabled(False)
                    self.signal_operat.emit(9, 1, [int(self.combox_index2.currentText())])
            else:
                pass
        else:
            if self.button_action.text() == '开始':
                self.tuple_dict = {}
                for i in range(len(self.edit_filename_list)):
                    if self.check_select_list[i].isChecked() is True:
                        if self.label_size_list[i].text() == '0':
                            QMessageBox.information(self, '提示', '第' + str(i+1) + '项目标尺寸不可为0!', QMessageBox.Yes)
                            return
                        elif self.edit_filename_list[i].hex_data is None:
                            QMessageBox.information(self, '提示', '请重新选取第' + str(i+1) + '项文件后重试!', QMessageBox.Yes)
                            return
                        elif int(self.label_size_list[i].text()) != self.edit_filename_list[i].data_size:
                            QMessageBox.information(self, '提示', '第' + str(i+1) + '项文件尺寸与目标尺寸不一致!', QMessageBox.Yes)
                            return
                        else:
                            self.tuple_dict[i] = list(((j,) + (len(tuple(self.edit_filename_list[i].hex_data[j:j + self.length_pack])),) + tuple(self.edit_filename_list[i].hex_data[j:j + self.length_pack])) for j in range(0, len(self.edit_filename_list[i].hex_data), self.length_pack))
                    else:
                        pass
                if self.tuple_dict:
                    self.send_batch_data_index = 0
                    self.send_index_index = 0
                    data_length = 0
                    for k in self.tuple_dict.keys():
                        data_length += len(self.edit_filename_list[k].hex_data)
                    self.progress_bar.setRange(0, data_length)
                    self.progress_bar.setValue(0)
                    self.button_action.setEnabled(False)
                    self.button_action.setText('传输中')
                    self.set_widget_enabled(False)
                    self.tuple_dict_key = list(self.tuple_dict.keys())
                    self.signal_operat.emit(9, 4, [None])
                    self.send_all()
                else:
                    QMessageBox.information(self, '提示', '没有可以烧写的项', QMessageBox.Yes)
                    return

            else:
                pass

    def send_all(self):
        self.signal_operat.emit(9, 5, [self.tuple_dict_key[self.send_index_index]])

    def response_addr_ok(self):
        self.send_batch_data_timer2.start(10)

    def send_batch_data_slot2(self):
        self.signal_operat.emit(9, 6, [self.tuple_dict[self.tuple_dict_key[self.send_index_index]][self.send_batch_data_index]])
        if self.send_batch_data_index < len(self.tuple_dict[self.tuple_dict_key[self.send_index_index]]):
            # self.send_batch_data_timer.start(10)
            pass
        else:
            # self.recv_host_data_timer.start(500)
            self.send_batch_data_timer2.stop()
            self.send_index_index += 1
            if self.send_index_index < len(self.tuple_dict_key):
                self.send_batch_data_index = 0
                self.send_all()
            else:
                self.button_action.setText('开始')
                self.button_action.setEnabled(True)
                self.set_widget_enabled(True)
                self.recover_scope_timer.start(500)
                self.label_text.setText('第' + str(self.tuple_dict_key).lstrip('[').rstrip(']') + '的结构体烧写成功')


    def response_request_continue2(self):
        self.progress_bar.setValue(self.progress_bar.value() + len(self.tuple_dict[self.tuple_dict_key[self.send_index_index]][self.send_batch_data_index]) - 2)
        self.send_batch_data_index += 1

    def response_request_stop2(self):
        self.send_batch_data_timer2.stop()
        QMessageBox.information(self, '批量写入数据', '批量写入数据失败!\n请检查后重试!')
        self.button_action.setText('开始')
        self.button_action.setEnabled(True)
        self.set_widget_enabled(True)
        self.recover_scope_timer.start(500)
        self.label_text.setText('尺寸为:' + self.label_size2.text() + '的结构体烧写失败')


    def show_MSG(self, MSG):
        QMessageBox.information(self, '提示', MSG, QMessageBox.Yes)
        self.button_action.setText('开始')
        self.button_action.setEnabled(True)
        self.set_widget_enabled(True)
        self.recover_scope_timer.start(500)

    def response_request_start(self):
        self.send_batch_data_timer.start(10)

    def response_request_continue(self):
        self.progress_bar.setValue(self.progress_bar.value() + len(self.tuple_list[self.send_batch_data_index]) - 2)
        self.send_batch_data_index += 1

    def response_request_stop(self):
        self.send_batch_data_timer.stop()
        QMessageBox.information(self, '批量写入数据', '批量写入数据失败!\n请检查后重试!')
        self.button_action.setText('开始')
        self.button_action.setEnabled(True)
        self.set_widget_enabled(True)
        self.recover_scope_timer.start(500)
        self.label_text.setText('尺寸为:' + self.label_size2.text() + '的结构体烧写失败')

    def send_batch_data_slot(self):
        self.signal_operat.emit(9, 2, [self.tuple_list[self.send_batch_data_index]])
        if self.send_batch_data_index < len(self.tuple_list):
            # self.send_batch_data_timer.start(10)
            pass
        else:
            # self.recv_host_data_timer.start(500)
            self.send_batch_data_timer.stop()
            self.button_action.setText('开始')
            self.button_action.setEnabled(True)
            self.set_widget_enabled(True)
            self.recover_scope_timer.start(500)
            self.label_text.setText('尺寸为:' + self.label_size2.text() + '的结构体烧写成功')
            pass

    def recover_scope_slot(self):
        self.signal_operat.emit(9, 3, [None])

    def closeEvent(self, event:PySide6.QtGui.QCloseEvent) -> None:
        """ 重写窗口的关闭事件 """
        if self.button_action.text() == '开始':
            if self.com_online_action.isChecked():
                self.get_config()
            super().closeEvent(event)
            self.signal_operat.emit(9, 0, [self.config])
        else:
            qm = QMessageBox.warning(self, "警告", "强行中断升级可能会引发意外!\n是否确认停止并退出",
                                     QMessageBox.Yes | QMessageBox.No)
            if qm == QMessageBox.Yes:
                if self.com_online_action.isChecked():
                    self.get_config()
                super().closeEvent(event)
                self.signal_operat.emit(9, 0, [self.config])
            else:
                event.ignore()

    def set_widget_enabled(self, flag):
        self.combox_index2.setEnabled(flag)
        self.button_read2.setEnabled(flag)
        for i in range(len(self.size_list)):
            if self.size_list[i] != 0:
                self.check_select_list[i].setEnabled(flag)
                self.button_read_list[i].setEnabled(flag)


class ClickableGroupBox(QGroupBox):
    clicked = Signal()
    top_left_range = QRect(0, 0, 60, 15)  # 定义左上角区域的范围

    def mouseDoubleClickEvent(self, event):
        if event.button() == Qt.LeftButton and self.top_left_range.contains(event.position().x(), event.position().y()):
            self.clicked.emit()

    # def mousePressEvent(self, event: QMouseEvent) -> None:
    #     if event.button() == Qt.LeftButton and self.top_left_range.contains(event.position().x(), event.position().y()):
    #         self.clicked.emit()



if __name__ == "__main__":
    app = QApplication(sys.argv)
    # apply_stylesheet(app, theme='light_teal.xml')     # 优化界面，暂时不用
    myWin = Struct_Write_Manage()
    myWin.show()
    sys.exit(app.exec())